package cn.fsd.service.impl;

import cn.fsd.domain.*;
import cn.fsd.mapper.*;
import cn.fsd.query.BaseQuery;
import cn.fsd.service.BaiduService;
import cn.fsd.service.OrderService;
import cn.fsd.vo.LocationPoint;
import cn.fsd.vo.OrderBean;
import cn.fsd.vo.PageBean;
import cn.hutool.core.lang.UUID;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    CommodityMapper commodityMapper;

    @Autowired
    CustomerMapper customerMapper;

    @Autowired
    Customer_addressMapper customer_addressMapper;

    @Autowired
    TaskMapper taskMapper;

    @Autowired
    StationMapper stationMapper;

    @Autowired
    StoreroomMapper storeroomMapper;

    @Autowired
    Storeroom_commodityMapper storeroom_commodityMapper;

    @Autowired
    TransferMapper transferMapper;

    @Autowired
    Transfer_pathMapper transfer_pathMapper;

    @Autowired
    BaiduService baiduService;

    @Override
    public PageBean<OrderBean> findByPage(BaseQuery query) {
        //构建结果对象
        PageBean<OrderBean> pageBean = new PageBean<>();

        //开启分页
        PageHelper.startPage(query.getPageNow(),query.getPageSize());

        //分页查询得到当页的集合
        List<OrderBean> orderBeanList = new ArrayList<>();
        List<Order> orderList = orderMapper.findByPage(query);
        for (int i = 0; i < orderList.size(); i++) {
            OrderBean orderBean = new OrderBean();
            Order order = orderList.get(i);
            orderBean.setOrder_id(order.getOrder_id());
            orderBean.setCommodity_id(order.getCommodity_id());
            orderBean.setCommodity_num(order.getCommodity_num());
            orderBean.setOrder_type(order.getOrder_type());
            orderBean.setOrder_status(order.getOrder_status());
            orderBean.setIs_invoice(order.getIs_invoice());
            orderBean.setNote(order.getNote());
            orderBean.setOperator_id(order.getOperator_id());
            orderBean.setDelivery_date(order.getDelivery_date());
            orderBean.setCommodity_name(commodityMapper.selectByPrimaryKey(order.getCommodity_id()).getCommodity_name());
            orderBean.setCustomer_name(customerMapper.selectByPrimaryKey(order.getCustomer_id()).getCustomer_name());
            Customer_address customer_address = customer_addressMapper.selectByPrimaryKey(order.getCustomer_id(), order.getAddress_choice());
            orderBean.setReceiver(customer_address.getReceiver());
            orderBean.setReceiver_address(customer_address.getReceiver_address());
            orderBean.setReceiver_phone(customer_address.getReceiver_phone());
            orderBean.setReceiver_postal_code(customer_address.getReceiver_postal_code());
            Task task = taskMapper.selectByOrderId(order.getOrder_id());
            if(task!=null) //订单列表查询时，由于部分订单未经过调度，不存在分站，那么station_id为null
                orderBean.setStation_id(task.getStation_id());
            orderBeanList.add(orderBean);
        }


        //创建一个分页的实体PageInfo
        PageInfo<OrderBean> pageInfo = new PageInfo<>(orderBeanList);


        //由于查询较复杂，直接使用pageHelper导致总记录和总页数计算有误，所以还是采用原始方法计算

//        pageBean.setTotalRows(pageInfo.getTotal());
//        pageBean.setTotalPages(pageInfo.getPages());

        //查询总记录
        int count = orderMapper.findCount(query);
        pageBean.setTotalRows((long)count);
        //计算总页数
        Integer pageSize = query.getPageSize();
        int totalPages = count%pageSize==0?count/pageSize:count/pageSize+1;
        pageBean.setTotalPages(totalPages);

        //pageInfo获取分页数据
        pageBean.setRowData(pageInfo.getList());

        return pageBean;
    }

    @Override
    public String update(String order_id) {
        Order order = orderMapper.selectByPrimaryKey(order_id);
        if("已挂起".equals(order.getOrder_status())){
            order.setOrder_status("可分配");
            int count = orderMapper.updateByPrimaryKey(order);
            if(count==1)
                return "success";
        }
        return "fail";
    }

    @Override
    public String transfer() {
        //一键调度先获取全部订单
        List<Order> orderList = orderMapper.selectAll();
        //遍历每个订单
        for (int i = 0; i < orderList.size(); i++) {
            //遍历到的当前订单
            Order order = orderList.get(i);
            //只有有货（订单状态为"可分配"）的订单才能进行调度
            if(order.getOrder_status().equals("可分配")){
                //******先生成任务单，taskservice的add方法
                //根据所查询到订单的customer_id和address_choice在customer_address表中查询对应的数据
                Customer_address customer_address = customer_addressMapper
                        .selectByPrimaryKey(order.getCustomer_id(), order.getAddress_choice());
                if(customer_address==null){//因为下面要用到customer_address的get方法，必须确保对象不为空
                    System.out.println("根据"+order.getOrder_id()+"号订单查询的customer_address对象为空，即无法获取收货人");
                    return "fail";
                }
                //获取到收货人地址
                String delivery_address = customer_address.getReceiver_address();
                //通过百度地图api查询地址对应的经纬度数据
                double[] deliveryLocationPoint = baiduService.getGeoByAddress(delivery_address);
                if(deliveryLocationPoint==null){
                    System.out.println(order.getOrder_id()+"号订单中的收货人地址有误，deliveryLocationPoint生成失败");
                    return "fail";
                }
                //遍历分站，通过百度地图api计算收货人地址到每个分站的距离和时间来选择分站（策略：优先选时间最短，时间相等选距离最短）
                List<Station> stationList = stationMapper.selectAll();
                int index = -1;//记录符合条件的分站下标
                double[] stationLocationPoint = new double[2];//记录所选分站地址对应的经纬度
                double minDistance = Integer.MAX_VALUE;
                double minTime = Integer.MAX_VALUE;
                for (int j = 0; j < stationList.size(); j++) {
                    //获取该分站地址
                    String station_place = stationList.get(j).getStation_place();
                    //通过百度地图api查询地址对应的经纬度数据
                    double[] stationTempLocationPoint = baiduService.getGeoByAddress(station_place);
                    if(stationTempLocationPoint==null){//分站地址无法逆编码时直接跳过
                        System.out.println("根据"+order.getOrder_id()+"号订单的收货人地址遍历寻找最佳分站时，"
                                +stationList.get(j).getStation_id()+"号分站地址解析有误，stationTempLocationPoint生成失败");
                        continue;}
                    //通过百度地图api计算收货人地址到每个分站的距离和时间
                    double[] distenceAndTime = baiduService.getDistenceAndTime(String.valueOf(deliveryLocationPoint[1]) + "," + String.valueOf(deliveryLocationPoint[0]), String.valueOf(stationTempLocationPoint[1]) + "," + String.valueOf(stationTempLocationPoint[0]));
                    if(distenceAndTime[1]<minTime){
                        index = j;
                        stationLocationPoint = stationTempLocationPoint;
                        minDistance = distenceAndTime[0];
                        minTime = distenceAndTime[1];
                    }else if(distenceAndTime[1]==minTime&&distenceAndTime[0]<minDistance){
                        index = j;
                        stationLocationPoint = stationTempLocationPoint;
                        minDistance = distenceAndTime[0];
                        minTime = distenceAndTime[1];}
                }
                Station station = stationList.get(index);
                Task task = new Task();
                task.setTask_id(UUID.randomUUID().toString());
                task.setOrder_id(order.getOrder_id());
                task.setStation_id(station.getStation_id());
                task.setTask_genDate(new Date());
                task.setCount_inTask(order.getCommodity_num());//商品数量
                task.setTask_status("调度中");//任务状态
                task.setCourier_id("-1");//配送员在分站管理的任务分配时指定
                //任务类型根据订单类型判断：新订订单对应送货任务，退换货订单对应相同任务名，退订不产生任务单
                String order_type = order.getOrder_type();
                if("新订".equals(order_type)){
                    task.setTask_type("送货");
                }else{
                    task.setTask_type(order_type);
                }
                //********以下字段需要根据需求设置*********
                task.setTask_finDate(new Date());//要求完成日期
                task.setTask_deliveryDate(new Date());//送货日期
                int count = taskMapper.insert(task);
                if(count!=1){
                    System.out.println("根据"+order.getOrder_id()+"号订单生成任务单失败");
                    return "fail";
                }

                //退货订单无需生成调拨单，但是生成任务单后订单状态仍为”可分配“，待点击“一键调度”后才修改为“调度中”
                //只有订单类型为非退货且已完成任务自动调度的才能生成调拨单
                if(!order.getOrder_type().equals("退货")){
                    //******再生成调拨单，transferservice的add方法
                    //查询订单中的商品id
                    String commodity_id = order.getCommodity_id();
                    //遍历库房，通过(查询库房对应商品的可分配量&&百度地图api计算所确定分站地址到每个库房的距离和时间)来选择库房（策略：优先选时间最短，时间相等选距离最短）
                    List<Storeroom> storeroomList = storeroomMapper.selectAll();
                    index = -1;//记录符合条件的库房下标
                    double[] storeroomLocationPoint = new double[2];//记录所选库房地址对应的经纬度
                    minDistance = Integer.MAX_VALUE;
                    minTime = Integer.MAX_VALUE;
                    for (int j = 0; j < storeroomList.size(); j++) {
                        //判断是否为中心库房
                        if(storeroomList.get(j).getStoreroom_level()==0){
                            //获取该库房地址
                            String storeroom_place = storeroomList.get(j).getStoreroom_place();
                            //通过百度地图api查询地址对应的经纬度数据
                            double[] storeroomTempLocationPoint = baiduService.getGeoByAddress(storeroom_place);
                            if(storeroomTempLocationPoint ==null){//分站地址无法逆编码时直接跳过
                                System.out.println("根据"+order.getOrder_id()+"号订单的已选分站地址遍历寻找最佳库房时，"
                                        +storeroomList.get(j).getStoreroom_id()+"号库房地址解析有误，storeroomTempLocationPoint");
                                continue;
                            }
                            //通过百度地图api计算收货人地址到每个分站的距离和时间
                            double[] distenceAndTime = baiduService.getDistenceAndTime(String.valueOf(stationLocationPoint[1]) + "," + String.valueOf(stationLocationPoint[0]), String.valueOf(storeroomTempLocationPoint[1]) + "," + String.valueOf(storeroomTempLocationPoint[0]));
                            if(distenceAndTime[1]<minTime){
                                index = j;
                                storeroomLocationPoint = storeroomTempLocationPoint;
                                minDistance = distenceAndTime[0];
                                minTime = distenceAndTime[1];
                            }else if(distenceAndTime[1]==minTime&&distenceAndTime[0]<minDistance){
                                index = j;
                                storeroomLocationPoint = storeroomTempLocationPoint;
                                minDistance = distenceAndTime[0];
                                minTime = distenceAndTime[1];
                            }
                        }
                    }
                    Storeroom storeroom = storeroomList.get(index);
                    //根据中心库房、分站库房位置，以及途径点来进行路线规划
                    String waypoints = null;
                    List<List<LocationPoint>> routes = baiduService.getRoute(String.valueOf(storeroomLocationPoint[1]) + "," + String.valueOf(storeroomLocationPoint[0]), String.valueOf(stationLocationPoint[1]) + "," + String.valueOf(stationLocationPoint[0]), waypoints);
                    //添加调度单
                    Transfer transfer = new Transfer();
                    String transfer_id = UUID.randomUUID().toString();
                    transfer.setTransfer_id(transfer_id);
                    transfer.setCommodity_id(commodity_id);
                    transfer.setStoreroom_id(storeroom.getStoreroom_id());
                    transfer.setStation_id(station.getStation_id());
                    transfer.setOrder_id(order.getOrder_id());
                    transfer.setPath_choice(0);//默认为0，即推荐路线
                    transfer.setTransfer_status("调度中");
                    transfer.setTransfer_sum(order.getCommodity_num());
                    //********以下字段需要根据需求设置*********
                    transfer.setOutbound_date(new Date());
                    int count_trans = transferMapper.insert(transfer);
                    //保存调度路径
                    int count_paths = 0;
                    for (int j = 0; j < routes.size(); j++) {
                        List<LocationPoint> route = routes.get(j);
                        if (route != null) {
                            Transfer_path transfer_path = new Transfer_path();
                            transfer_path.setTransfer_id(transfer_id);
                            transfer_path.setPath_num(j);
                            transfer_path.setPath_info(route.toString());
                            int count_path = transfer_pathMapper.insert(transfer_path);
                            count_paths += count_path;
                        }
                    }
                    if(count_trans!=1||count_paths!=routes.size()){
                        System.out.println(order.getOrder_id()+"号订单的库房调拨失败");
                        return "fail";
                    }
                }
            }
        }
        return "success";
    }

    @Override
    public String transferById(String order_id) {
        //查询到的当前订单
        Order order = orderMapper.selectByPrimaryKey(order_id);
        //任何订单在创建后都要先提前进行自动调度
        //******先生成任务单，taskservice的add方法
        //根据所查询到订单的customer_id和address_choice在customer_address表中查询对应的数据
        Customer_address customer_address = customer_addressMapper.selectByPrimaryKey(order.getCustomer_id(), order.getAddress_choice());
        if(customer_address==null){//因为下面要用到customer_address的get方法，必须确保对象不为空
            System.out.println("根据"+order.getOrder_id()+"号订单查询的customer_address对象为空，即无法获取收货人");
            return "fail";
        }
        //获取到收货人地址
        String delivery_address = customer_address.getReceiver_address();
        //通过百度地图api查询地址对应的经纬度数据
        double[] deliveryLocationPoint = baiduService.getGeoByAddress(delivery_address);
        if(deliveryLocationPoint==null){
            System.out.println(order.getOrder_id()+"号订单中的收货人地址有误，deliveryLocationPoint生成失败");
            return "fail";
        }
        //遍历分站，通过百度地图api计算收货人地址到每个分站的距离和时间来选择分站（策略：优先选时间最短，时间相等选距离最短）
        List<Station> stationList = stationMapper.selectAll();
        int index = -1;//记录符合条件的分站下标
        double[] stationLocationPoint = new double[2];//记录所选分站地址对应的经纬度
        double minDistance = Integer.MAX_VALUE;
        double minTime = Integer.MAX_VALUE;
        for (int j = 0; j < stationList.size(); j++) {
            //获取该分站地址
            String station_place = stationList.get(j).getStation_place();
            //通过百度地图api查询地址对应的经纬度数据
            double[] stationTempLocationPoint = baiduService.getGeoByAddress(station_place);
            if(stationTempLocationPoint==null){//分站地址无法逆编码时直接跳过
                System.out.println("根据"+order.getOrder_id()+"号订单的收货人地址遍历寻找最佳分站时，"+stationList.get(j).getStation_id()+"号分站地址解析有误，stationTempLocationPoint生成失败");
                continue;
            }
            //通过百度地图api计算收货人地址到每个分站的距离和时间
            double[] distenceAndTime = baiduService.getDistenceAndTime(String.valueOf(deliveryLocationPoint[1]) + "," + String.valueOf(deliveryLocationPoint[0]), String.valueOf(stationTempLocationPoint[1]) + "," + String.valueOf(stationTempLocationPoint[0]));
            if(distenceAndTime[1]<minTime){
                index = j;
                stationLocationPoint = stationTempLocationPoint;
                minDistance = distenceAndTime[0];
                minTime = distenceAndTime[1];
            }else if(distenceAndTime[1]==minTime&&distenceAndTime[0]<minDistance){
                index = j;
                stationLocationPoint = stationTempLocationPoint;
                minDistance = distenceAndTime[0];
                minTime = distenceAndTime[1];
            }
        }
        Station station = stationList.get(index);
        Task task = new Task();
        task.setTask_id(UUID.randomUUID().toString());
        task.setOrder_id(order.getOrder_id());
        task.setStation_id(station.getStation_id());
        task.setTask_genDate(new Date());
        task.setCount_inTask(order.getCommodity_num());//商品数量
        task.setTask_status("未处理");//任务状态
        task.setCourier_id("-1");//配送员在分站管理的任务分配时指定
        //任务类型根据订单类型判断：新订订单对应送货任务，退换货订单对应相同任务名，退订不产生任务单
        String order_type = order.getOrder_type();
        System.out.println(order_type);
        if("新订".equals(order_type)){
            task.setTask_type("送货");
        }else{
            task.setTask_type(order_type);
        }
        //********以下字段需要根据需求设置*********
        task.setTask_finDate(new Date());//要求完成日期
        task.setTask_deliveryDate(new Date());//送货日期
        int count = taskMapper.insert(task);
        if(count!=1){
            System.out.println("根据"+order.getOrder_id()+"号订单生成任务单失败");
            return "fail";
        }

        //退货订单无需生成调拨单，但是生成任务单后订单状态仍为”可分配“，待点击“一键调度”后才修改为“调度中”
        //只有订单类型为非退货且已完成任务自动调度的才能生成调拨单
        if(!order.getOrder_type().equals("退货")){
            //******再生成调拨单，transferservice的add方法
            //查询订单中的商品id
            String commodity_id = order.getCommodity_id();
            //遍历库房，通过(查询库房对应商品的可分配量&&百度地图api计算所确定分站地址到每个库房的距离和时间)来选择库房（策略：优先选时间最短，时间相等选距离最短）
            List<Storeroom> storeroomList = storeroomMapper.selectAll();
            index = -1;//记录符合条件的库房下标
            double[] storeroomLocationPoint = new double[2];//记录所选库房地址对应的经纬度
            minDistance = Integer.MAX_VALUE;
            minTime = Integer.MAX_VALUE;
            for (int j = 0; j < storeroomList.size(); j++) {
                //判断是否为中心库房
                if(storeroomList.get(j).getStoreroom_level()==0){
                    //获取该库房地址
                    String storeroom_place = storeroomList.get(j).getStoreroom_place();
                    //通过百度地图api查询地址对应的经纬度数据
                    double[] storeroomTempLocationPoint = baiduService.getGeoByAddress(storeroom_place);
                    if(storeroomTempLocationPoint ==null){//分站地址无法逆编码时直接跳过
                        System.out.println("根据"+order.getOrder_id()+"号订单的已选分站地址遍历寻找最佳库房时，"+storeroomList.get(j).getStoreroom_id()+"号库房地址解析有误，storeroomTempLocationPoint");
                        continue;
                    }
                    //通过百度地图api计算收货人地址到每个分站的距离和时间
                    double[] distenceAndTime = baiduService.getDistenceAndTime(String.valueOf(stationLocationPoint[1]) + "," + String.valueOf(stationLocationPoint[0]), String.valueOf(storeroomTempLocationPoint[1]) + "," + String.valueOf(storeroomTempLocationPoint[0]));
                    if(distenceAndTime[1]<minTime){
                        index = j;
                        storeroomLocationPoint = storeroomTempLocationPoint;
                        minDistance = distenceAndTime[0];
                        minTime = distenceAndTime[1];
                    }else if(distenceAndTime[1]==minTime&&distenceAndTime[0]<minDistance){
                        index = j;
                        storeroomLocationPoint = storeroomTempLocationPoint;
                        minDistance = distenceAndTime[0];
                        minTime = distenceAndTime[1];
                    }
                }
            }
            Storeroom storeroom = storeroomList.get(index);
            //根据中心库房、分站库房位置，以及途径点来进行路线规划
            String waypoints = null;
            List<List<LocationPoint>> routes = baiduService.getRoute(String.valueOf(storeroomLocationPoint[1]) + "," + String.valueOf(storeroomLocationPoint[0]), String.valueOf(stationLocationPoint[1]) + "," + String.valueOf(stationLocationPoint[0]), waypoints);
            //添加调度单
            Transfer transfer = new Transfer();
            String transfer_id = UUID.randomUUID().toString();
            transfer.setTransfer_id(transfer_id);
            transfer.setCommodity_id(commodity_id);
            transfer.setStoreroom_id(storeroom.getStoreroom_id());
            transfer.setStation_id(station.getStation_id());
            transfer.setOrder_id(order.getOrder_id());
            transfer.setPath_choice(0);//默认为0，即推荐路线
            transfer.setTransfer_status("未处理");
            transfer.setTransfer_sum(order.getCommodity_num());
            //********以下字段需要根据需求设置*********
            transfer.setOutbound_date(new Date());
            int count_trans = transferMapper.insert(transfer);
            //保存调度路径
            int count_paths = 0;
            for (int j = 0; j < routes.size(); j++) {
                List<LocationPoint> route = routes.get(j);
                if (route != null) {
                    Transfer_path transfer_path = new Transfer_path();
                    transfer_path.setTransfer_id(transfer_id);
                    transfer_path.setPath_num(j);
                    transfer_path.setPath_info(route.toString());
                    int count_path = transfer_pathMapper.insert(transfer_path);
                    count_paths += count_path;
                }
            }
            if(count_trans!=1||count_paths!=routes.size()){
                System.out.println(order.getOrder_id()+"号订单的库房调拨失败");
                return "fail";
            }
        }
        return "success";
    }

    @Override
    public String transferAll() {
        List<Order> orderList = orderMapper.selectAll();
        for (int i = 0; i < orderList.size(); i++) {
            Order order = orderList.get(i);
            //只有可分配状态的订单才能进行调度，这里实际只是修改状态
            if("可分配".equals(order.getOrder_status())){
                order.setOrder_status("调度中");
                int count = orderMapper.updateByPrimaryKey(order);
                if(count!=1)
                    return "fail";
                Task task = taskMapper.selectByOrderId(order.getOrder_id());
                if("未处理".equals(task.getTask_status())){
                    task.setTask_status("调度中");
                    count = taskMapper.updateByPrimaryKey(task);
                    if(count!=1)
                        return "fail";
                }
                //非退货订单才有调拨单
                if(!"退货".equals(order.getOrder_type())){
                    Transfer transfer = transferMapper.selectByOrderId(order.getOrder_id());
                    if("未处理".equals(transfer.getTransfer_status())){
                        transfer.setTransfer_status("调度中");
                        count = transferMapper.updateByPrimaryKey(transfer);
                        if(count!=1)
                            return "fail";
                    }
                }
            }
        }
        return "success";
    }
}
